﻿
namespace Bildverarbeitung
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Imaging;
    using AForge.Imaging.Filters;
    using AForge.Imaging;
    using AForge;

    public class HaasBastianFilter : IFilter
    {
        private Bitmap[] imageList;
        UnmanagedImage result;

        public String GetName()
        {
            return ("HaasBastian");
        }

        // private format translation dictionary
        private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();

        public Dictionary<PixelFormat, PixelFormat> FormatTranslations
        {
            get { return formatTranslations; }
        }

        public HaasBastianFilter()
        {
            formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed;
            formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb;
            formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb;
            formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb;

        }

        public Bitmap GetSummerizedDifferencefromAverage(Bitmap[] images)
        {
            if (images.Length < 1)
            {
                System.Console.WriteLine("Kein Image gefunden!");
                return null;
            }
            else
            {
                this.imageList = images;
                result = UnmanagedImage.FromManagedImage(images[0]);
                Rectangle rect = new Rectangle(0, 0, images[0].Width, images[0].Height);
                ProcessFilter(result, rect);
                Bitmap newResult = result.ToManagedImage();
                return newResult;
            }
        }

        protected unsafe void ProcessFilter(UnmanagedImage destination, Rectangle rect)
        {
            //UnmanagedImage source;
            UnmanagedImage[] unmanagedImageList = new UnmanagedImage[imageList.Length];

            //Pointer
            byte*[] src = new byte*[imageList.Length];

            for (int i = 0; i < unmanagedImageList.Length; i++)
            {
                unmanagedImageList[i] = (UnmanagedImage.FromManagedImage(imageList[i]));
                src[i] = (byte*)unmanagedImageList[i].ImageData.ToPointer();
            }

            byte* dst = (byte*)destination.ImageData.ToPointer();

            //PixelSize
            int pixelSize = System.Drawing.Image.GetPixelFormatSize(unmanagedImageList[0].PixelFormat) / 8;
            //int pixelSize = (unmanagedImageList[0].PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;

            // processing start and stop X,Y positions
            int startX = rect.Left;
            int startY = rect.Top;
            int stopX = startX + rect.Width;
            int stopY = startY + rect.Height;

            int srcStride = unmanagedImageList[0].Stride;
            int dstStride = destination.Stride;
            int srcOffset = srcStride - rect.Width * pixelSize;
            int dstOffset = srcStride - rect.Width * pixelSize;

            // allign pointers to the first pixel to process
            for (int i = 0; i < imageList.Length; i++)
            {
                src[i] += (startY * srcStride + startX * pixelSize);
            }
            dst += (startY * dstStride + startX * pixelSize);

            /*Avarage
            int red = 0;
            int green = 0;
            int blue = 0;
            */

            // for each line
            for (int y = startY; y < stopY; y++)
            {
                // for each pixel
                for (int x = startX; x < stopX; x++, dst += pixelSize)
                {
                    /* Avarage
                    red = 0;
                    green = 0;
                    blue = 0;
                    */

                    int[] r = new int[src.Length];
                    int[] g = new int[src.Length];
                    int[] b = new int[src.Length];

                    for (int i = 0; i < src.Length; i++)
                    {
                        r[i] = src[i][RGB.R];
                        g[i] = src[i][RGB.G];
                        b[i] = src[i][RGB.B];

                        /*Avarage
                        // red
                        red += src[i][RGB.R];// p[RGB.R];                     
                        // green
                        green += src[i][RGB.G];// p[RGB.G];
                        // blue
                        blue += src[i][RGB.B];//p[RGB.B];
                        */

                        src[i] += pixelSize;
                    }

                    Array.Sort(r);
                    Array.Sort(g);
                    Array.Sort(b);

                    int finalRed = r[src.Length / 2];
                    int finalGreen = g[src.Length / 2];
                    int finalBlue = b[src.Length / 2];

                    /*Avarage
                    int finalRed = red / src.Length;
                    int finalGreen = green / src.Length;
                    int finalBlue = blue / src.Length;
                    */

                    /*------------------ lustiger filter ;)
                    int finalRed = 0;
                    int finalGreen = 0;
                    int finalBlue = 0;
                    for (int j = 0; j < src.Length; j++)
                    {
                        finalRed += red;
                        finalGreen += green;
                        finalBlue += blue;
                        src[j] += pixelSize;
                    }
                    finalRed = finalRed / src.Length;
                    finalGreen = finalGreen / src.Length;
                    finalBlue = finalBlue / src.Length;
                    ----------------------------*/

                    // set destination pixel
                    dst[RGB.R] = (byte)(finalRed);
                    dst[RGB.G] = (byte)(finalGreen);
                    dst[RGB.B] = (byte)(finalBlue);

                    for (int j = 0; j < src.Length; j++)
                    {
                        src[j] += srcOffset;
                    }
                    dst += dstOffset;
                }
            }
        }
    }
}
